package server

import (
	"fmt"
	"server5/Interface"
	"server5/protobuf"
	"server5/utils"
	"time"
)

type Stronghold struct {
	id              int32               //据点id
	Type            int32               //据点类型，城堡，村庄，魔法塔
	level           int32               //据点等级
	player          Interface.IPlayer   //所属玩家，中立据点未被占领为nil
	occupyPlayer	Interface.IPlayer	//上次占领这个据点的玩家，主要用于中立建筑读条是否清零
	gameRoom        Interface.IGameRoom //所属游戏房间
	posX            int32               //位置
	posZ            int32               //位置
	status          int32               //状态，正常状态（占领进度为零），被占领中状态，
	pop             int32               //能够提供的人口数量
	moneyAdd		int32				//金币增长
	magicAdd		int32				//魔法增长
	bar             int32               //占领进度
	occupyUnitId    int32               //上次和正在占领这个据点的士兵Id
	occupyMoney		int32				//占领成功获得的金币数
	lastOccupyTime  time.Time           //开始占领的时间
	lands 			[]Interface.ILand
}

func (s *Stronghold) MagicAdd() int32 {
	return s.magicAdd
}

func (s *Stronghold) MoneyAdd() int32 {
	return s.moneyAdd
}

func (s *Stronghold) OccupyPlayer() Interface.IPlayer {
	return s.occupyPlayer
}

func (s *Stronghold) SetOccupyPlayer(occupyPlayer Interface.IPlayer) {
	s.occupyPlayer = occupyPlayer
}

func (s *Stronghold) Bar() int32 {
	return s.bar
}

func (s *Stronghold) SetBar(bar int32) {
	s.bar = bar
}

func (s *Stronghold) OccupyUnitId() int32 {
	return s.occupyUnitId
}

func (s *Stronghold) SetOccupyUnitId(occupyUnitId int32) {
	s.occupyUnitId = occupyUnitId
}

func (s *Stronghold) CancelOccupy(unitId int32) {
	//TODO 取消占领
	if s.occupyUnitId != unitId {
		//Debug
		fmt.Println("取消占领失败")
		return
	}
	s.status = utils.Normal
	s.occupyUnitId = 0
	//Debug
	fmt.Println("取消占领成功")
}

func (s *Stronghold) Occupy() bool {
	if s.status == utils.Normal || s.occupyUnitId == 0 {
		//正常状态，不占领
		return false
	}
	t := time.Now()
	if t.Sub(s.lastOccupyTime).Seconds() >= 1 {
		s.lastOccupyTime = t
		s.bar++
		fmt.Println("占领进度", s.bar)

		var occupyStrongholdResultMsg protobuf.OccupyStrongholdResultMsg
		occupyStrongholdResultMsg.UnitId = s.occupyUnitId
		occupyStrongholdResultMsg.StrongholdId = s.id
		occupyStrongholdResultMsg.Bar = float64(s.bar) / 15
		occupyStrongholdResultMsg.Success = false

		if s.bar >= 15 {
			fmt.Println("占领成功")

			occupyStrongholdResultMsg.Success = true
			//改变玩家的据点列表
			if s.player != nil {
				s.player.RemoveStronghold(s.id)
				s.player.ReCalculate()
			}
			s.gameRoom.GetUnit(s.occupyUnitId).Player().AddStronghold(s)

			for _,l := range s.lands {
				l.ToLand()
				var updateLandMsg protobuf.UpdateLandMsg
				updateLandMsg.Stronghold = s.Id()
				updateLandMsg.LandId = l.Id() - 1
				updateLandMsg.LandType = l.LandType()

				s.gameRoom.Broadcast(protobuf.MsgType_UpdateLand,&updateLandMsg)
			}
			s.gameRoom.GetUnit(s.occupyUnitId).Player().AddMoney(s.occupyMoney)
			s.gameRoom.GetUnit(s.occupyUnitId).Player().ReCalculate()

			s.player = s.gameRoom.GetUnit(s.occupyUnitId).Player()
			s.player.GameRoom().Broadcast(protobuf.MsgType_OccupyStrongholdResult, &occupyStrongholdResultMsg)

			s.status = utils.Normal
			s.bar = 0
			s.occupyUnitId = 0
			return true
		}
		s.gameRoom.Broadcast(protobuf.MsgType_OccupyStrongholdResult, &occupyStrongholdResultMsg)
	}
	return false
}

func (s *Stronghold) Level() int32 {
	return s.level
}

func (s *Stronghold) SetLevel(level int32) {
	s.level = level
}

func (s *Stronghold) UpdateLand(landId int32,landType int32) {
	//先检测数据正确性
	if landId > int32(len(s.lands)) {
		fmt.Println("此据点没有这个空地")
		return
	}

	l := s.lands[landId - 1]
	//Debug
	fmt.Println("此空地现在的类型为",l.LandType())

	//根据landType执行不同操作
	switch landType {
	case utils.Land:
		l.ToLand()
	case utils.MagicStone:
		if s.player.Money() >= utils.MagicStoneMoney && l.LandType() == utils.Land {
			s.player.AddMoney(-utils.MagicStoneMoney)
			l.ToMagicStone()
		}
	case utils.Farm:
		if s.player.Money() >= utils.FarmMoney && l.LandType() == utils.Land {
			s.player.AddMoney(-utils.FarmMoney)
			l.ToFarm()
		}
	case utils.Mine:
		if s.player.Money() >= utils.MineMoney && l.LandType() == utils.Land {
			s.player.AddMoney(-utils.MineMoney)
			l.ToMine()
		}
	}
	//重新计算
	s.player.ReCalculate()

	//Debug
	fmt.Println("建造成功",s.id,landId,l.LandType())

	var updateLandMsg protobuf.UpdateLandMsg
	updateLandMsg.Stronghold = s.Id()
	updateLandMsg.LandId = landId
	updateLandMsg.LandType = l.LandType()

	s.gameRoom.Broadcast(protobuf.MsgType_UpdateLand,&updateLandMsg)
}



//重新计算该据点的人口，金币和魔法增长
func (s *Stronghold) ReCalculate() {
	s.pop = 0
	s.moneyAdd = 0
	s.magicAdd = 0
	for _, l := range s.lands {
		s.pop += l.Pop()
		s.moneyAdd += l.MoneyAdd()
		s.magicAdd += l.MagicAdd()
	}
	switch s.Type {
	case utils.Castle:
		s.pop += utils.CastlePop
		s.moneyAdd += utils.CastleMoneyAdd
		s.magicAdd += utils.CastleMagicAdd
	case utils.Village:
		s.pop += utils.VillagePop
		s.moneyAdd += utils.VillageMoneyAdd
		s.magicAdd += utils.VillageMagicAdd
	case utils.MagicTower:
		s.pop += utils.MagicTowerPop
		s.moneyAdd += utils.MagicTowerMoneyAdd
		s.magicAdd += utils.MagicTowerMagicAdd
	}
}


//城堡
func NewCastle(id int32,player Interface.IPlayer,room Interface.IGameRoom) *Stronghold {
	s := &Stronghold{
		id: id,
		Type: utils.Castle,
		level: 1,
		player: player,
		status: utils.Normal,
		gameRoom: room,
		lands: make([]Interface.ILand, utils.CastleLandNum),
		occupyMoney: utils.CastleOccupyMoney,
		//posX
		//posZ
	}
	for i := int32(0); i < utils.CastleLandNum; i++ {
		s.lands[i] = NewLand(i + 1, s)
	}
	s.ReCalculate()
	return s
}

//村庄
func NewVillage(id int32,player Interface.IPlayer,room Interface.IGameRoom) *Stronghold {
	s := &Stronghold{
		id: id,
		Type: utils.Village,
		level: 1,
		player: player,
		status: utils.Normal,
		gameRoom: room,
		lands: make([]Interface.ILand, utils.VillageLandNum),
		occupyMoney: utils.VillageOccupyMoney,
		//posX
		//posZ
	}
	for i := int32(0); i < utils.VillageLandNum; i++ {
		s.lands[i] = NewLand(i + 1, s)
	}
	s.ReCalculate()
	return s
}


//魔法塔
func NewMagicTower(id int32,player Interface.IPlayer,room Interface.IGameRoom) *Stronghold {
	s := &Stronghold{
		id: id,
		Type: utils.MagicTower,
		level: 1,
		player: player,
		status: utils.Normal,
		gameRoom: room,
		lands: make([]Interface.ILand, utils.MagicTowerLandNum),
		occupyMoney: utils.MagicTowerOccupyMoney,
		//posX
		//posZ
	}
	for i := int32(0); i < utils.MagicTowerLandNum; i++ {
		s.lands[i] = NewLand(i + 1, s)
	}
	s.ReCalculate()
	return s
}

func (s *Stronghold) UpLevel() bool {
	switch s.level {
	case 1:
		if s.player.Money() >= utils.CastleUpTo2Money {
			s.level++
			s.player.AddMoney(-utils.CastleUpTo2Money)
			return true
		}
	case 2:
		if s.player.Money() >= utils.CastleUpTo3Money {
			s.level++
			s.player.AddMoney(-utils.CastleUpTo3Money)
			return true
		}
	}
	return false
}

func (s *Stronghold) BuyUnit(unitId int32,unitType int32) bool {

	if unitType == utils.Boss {
		return s.BuyBoss(unitId)
	}

	if s.player.Pop() >= s.player.MaxPop() {
		fmt.Println("人口不足，不能再购买士兵")
		return false
	}

	switch unitType {
	case utils.Infantry:
		return s.BuyInfantry(unitId)
	case utils.Archer:
		return s.BuyArcher(unitId)
	case utils.Mage:
		return s.BuyMage(unitId)
	}
	return false
}

//购买步兵
func (s *Stronghold) BuyInfantry(unitId int32) bool {
	//所有据点都可购买步兵
	if s.player.Money() >= utils.InfantryPrice {
		u := NewInfantry(unitId,s.level,s.player)
		s.player.AddUnit(u)
		s.player.GameRoom().AddUnit(u)
		s.player.AddMoney(-utils.InfantryPrice)
		s.player.SetPop(s.player.Pop() + 1)
		buyUnitResultMsg := protobuf.BuyUnitResultMsg{
			PlayerId: s.player.PlayerId(),
			StrongholdId: s.id,
			UnitId: unitId,
			UnitType: utils.Infantry,
			UnitLevel: s.level,
			AllHp: u.AllHp(),
			AttackRange: u.AttackRange(),
			DetectRange: u.DetectRange(),
		}
		s.player.GameRoom().Broadcast(protobuf.MsgType_BuyUnitResult,&buyUnitResultMsg)
		return true
	}
	return false
}

//购买弓兵
func (s *Stronghold) BuyArcher(unitId int32) bool {
	//魔法塔不能购买弓兵
	if s.Type == utils.MagicTower {
		return false
	}
	if s.player.Money() >= utils.ArcherPrice {
		u := NewArcher(unitId,s.level,s.player)
		s.player.AddUnit(u)
		s.player.GameRoom().AddUnit(u)
		s.player.AddMoney(-utils.ArcherPrice)
		s.player.SetPop(s.player.Pop() + 1)
		buyUnitResultMsg := protobuf.BuyUnitResultMsg{
			PlayerId: s.player.PlayerId(),
			StrongholdId: s.id,
			UnitId: unitId,
			UnitType: utils.Archer,
			UnitLevel: s.level,
			AllHp: u.AllHp(),
			AttackRange: u.AttackRange(),
			DetectRange: u.DetectRange(),
		}
		s.player.GameRoom().Broadcast(protobuf.MsgType_BuyUnitResult,&buyUnitResultMsg)
		return true
	}
	return false
}

//购买法师
func (s *Stronghold) BuyMage(unitId int32) bool {
	//只有魔法塔能购买法师
	//if s.Type != utils.MagicTower {
	//	return false
	//}
	if s.player.Money() >= utils.MagePrice {
		u := NewMage(unitId,s.level,s.player)
		s.player.AddUnit(u)
		s.player.GameRoom().AddUnit(u)
		s.player.AddMoney(-utils.MagePrice)
		s.player.SetPop(s.player.Pop() + 1)
		buyUnitResultMsg := protobuf.BuyUnitResultMsg{
			PlayerId: s.player.PlayerId(),
			StrongholdId: s.id,
			UnitId: unitId,
			UnitType: utils.Mage,
			UnitLevel: s.level,
			AllHp: u.AllHp(),
			AttackRange: u.AttackRange(),
			DetectRange: u.DetectRange(),
		}
		s.player.GameRoom().Broadcast(protobuf.MsgType_BuyUnitResult,&buyUnitResultMsg)
		return true
	}
	return false
}


//购买Boss
func (s *Stronghold) BuyBoss(unitId int32) bool {
	//使用魔法值召唤，并且不占用人口
	if s.player.Magic() >= utils.BossPrice {
		u := NewBoss(unitId,s.level,s.player)
		s.player.AddUnit(u)
		s.player.GameRoom().AddUnit(u)
		s.player.AddMagic(-utils.BossPrice)
		buyUnitResultMsg := protobuf.BuyUnitResultMsg{
			PlayerId: s.player.PlayerId(),
			StrongholdId: s.id,
			UnitId: unitId,
			UnitType: utils.Boss,
			UnitLevel: s.level,
			AllHp: u.AllHp(),
			AttackRange: u.AttackRange(),
			DetectRange: u.DetectRange(),
		}
		s.player.GameRoom().Broadcast(protobuf.MsgType_BuyUnitResult,&buyUnitResultMsg)
		return true
	}
	return false
}


func (s *Stronghold) Pop() int32 {
	return s.pop
}

func (s *Stronghold) SetPop(pop int32) {
	s.pop = pop
}

func (s *Stronghold) Status() int32 {
	return s.status
}

func (s *Stronghold) SetStatus(status int32) {
	s.status = status
}

func (s *Stronghold) PosZ() int32 {
	return s.posZ
}

func (s *Stronghold) SetPosZ(posZ int32) {
	s.posZ = posZ
}

func (s *Stronghold) PosX() int32 {
	return s.posX
}

func (s *Stronghold) SetPosX(posX int32) {
	s.posX = posX
}

func (s *Stronghold) Player() Interface.IPlayer {
	return s.player
}

func (s *Stronghold) SetPlayer(player Interface.IPlayer) {
	s.player = player
}

func (s *Stronghold) Id() int32 {
	return s.id
}

func (s *Stronghold) SetId(id int32) {
	s.id = id
}